<!--
/**
 * SPDX-FileCopyrightText: 2022-2023 Zeal 8-bit Computer <contact@zeal8bit.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Zeal 8-bit Computer Emulator</title>
    <link rel="stylesheet" href="xterm/xterm.css" />
    <script src="crypto/sha256.js"></script>
    <script src="xterm/xterm.js"></script>
    <link rel="stylesheet" type="text/css" href="emulator.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="interface.css" media="screen" />
  </head>

  <body>
    <section id="popup-message">
    </section>
    <section id="blackbg"></section>

    <section class="popup" id="about-message">
        <h2>About Zeal 8-bit Computer emulator</h2>
        <p>The purpose of this project is to provide an easy way to try Zeal 8-bit Computer, as well as develop and debug for it thanks to the embedded debugger. The emulation is <strong>cycle accurate</strong>, so the behavior of the programs run inside this emulator should be the exact same as on the real hardware.</p>
        <figure>
          <img src="imgs/help/motherboard.png" alt="Zeal 8-bit Motherboard" />
          <figcaption>Zeal 8-bit Computer Motherboard</figcaption>
        </figure>

        <p>You can find more information about <a href="https://www.youtube.com/c/Zeal8bitComputer"><strong>Zeal 8-bit Computer on Youtube</strong></a> or on the project official website <a href="https://zeal8bit.com"><strong>zeal8bit.com</strong></a></p>
        <h3>Source code</h3>
        <p>The source code of the emulator is available on the official Github repository: <a href="https://github.com/Zeal8bit/Zeal-WebEmulator"><strong>https://github.com/Zeal8bit/Zeal-WebEmulator</strong></a></p>
        <h3>Licence</h3>
        <p>The CPU core (<code>Z80.js</code>) is distributed  under the MIT license (originated from <a href="https://github.com/DrGoldfire/Z80.js">Molly Howell repository</a>)</p>
        <p>All the other files of the project are distributed under the Apache 2.0 License.</p>
        <h3>Credits</h3>
        <p>People involved in the project:</p>
        <ul>
        <li><a href="https://github.com/Zeal8bit">Zeal8bit</a>: owner, main developer and maintainer</li>
        <li><a href="https://github.com/JasonMo1">JasonMo</a>: contributor</li>
        </ul>
        <p>For more details about the contributors, <a href="https://github.com/Zeal8bit/Zeal-WebEmulator/graphs/contributors">follow this link</a>.</p>
    </section>
    <section class="popup" id="help-message" markdown="1">
        <h2>Getting started with the emulator</h2>
        <p>The interface of Zeal 8-bit Computer emulator is rich in tools. They make it possible to simulate almost every part of the actual computer.</p>
        <figure>
          <img src="imgs/help/gui.png" alt="GUI" />
          <figcaption>Interface organization</figcaption>
        </figure>

        <ol>
        <li>ROM/EEPROM loading</li>
        <li>Emulated screen and PS/2 keyboard</li>
        <li>Bottom views: disassembler, memory viewer and UART monitor</li>
        <li>Debugging actions: start/resume CPU, step in, step over, stop, reset, clean</li>
        <li>Breakpoint management</li>
        <li>CPU registers value</li>
        </ol>
        <h3>Loading a ROM</h3>
        <p>Loading a ROM can be done through the left panel section:</p>
        <figure>
          <img src="imgs/help/rom.png" alt="ROM Selection" />
          <figcaption>ROM Selection</figcaption>
        </figure>

        <p>The emulator offers two ways to load code inside the ROM:</p>
        <ul>
        <li>Select a pre-built ROM image of Zeal 8-bit OS. This includes the latest version, nightly builds and the releases. All of them are compiled from <a href="https://github.com/Zeal8bit/Zeal-8-bit-OS">Zeal 8-bit OS official repository</a>.</li>
        <li>Load your own image of the ROM, and an optional (64KB) EEPROM image. Since the images will directly be copied inside the emulated ROM and EEPROM respectively, this image <strong>does not</strong> necessarily contain Zeal 8-bit OS, it can contain any Z80 code. The <code>system map</code> file, as its name states, is the <code>.map</code> file generated by <code>z88dk-z80asm</code> when assembling a program. Providing this file will add symbols inside the disassembler.</li>
        </ul>
        <p>The first option is preferred if you want to quickly test Zeal 8-bit OS, or if you want to load your own programs, while the second option is preferred if you want to debug the operating system itself or a ROM image you have.</p>
        <blockquote>
        <p><strong>Note:</strong> when loading your own images and clicking <code>Read file(s)</code> button, it is necessary to press debugger's <code>Continue</code> button to start the CPU!</p>
        </blockquote>
        <h3>Emulated screen and PS/2 keyboard</h3>
        <p>At the middle of the interface lies a 640x480px canvas that emulates Zeal 8-bit VGA video board. This interface will draw all the pixels that would be drawn by the VGA video board.</p>
        <figure>
          <img src="imgs/help/screen.png" alt="Screen" />
          <figcaption>Screen emulation</figcaption>
        </figure>

        <p>This canvas also contains a keyboard listener that will send all the keys typed to the PS/2 protocol emulator. Therefore, the canvas <strong>must be focused first</strong> (by clicking on it) before trying to type anything.</p>
        <h3>Disassembler</h3>
        <p>The disassembler, as its name states, disassembles the binary code being executed by the Z80 CPU into assembly code. It also shows the current breakpoints with a small red dot on the left. It is possible to add or remove breakpoints from there by clicking on the corresponding instruction.</p>
        <figure>
          <img src="imgs/help/disassembler.png" alt="Disassembler" />
          <figcaption>Disassembler view</figcaption>
        </figure>

        <p>The current instruction (current PC) will always be at the top of the disassembler view. The format of each line is as follows:</p>
        <p><code>[dot]       instruction         ; [virtual address] raw bytes of the instruction</code></p>
        <p>The code is only disassembled when the CPU is <strong>stopped</strong>, either because it encountered a breakpoint or when the <code>stop</code> button is manually pressed.</p>
        <blockquote>
        <p><strong>Note:</strong> If a <code>.map</code> file was provided when loading the ROM, the symbols, such as the routines or labels name, will also be shown. Constants are not replaced in <code>ld</code> or related instructions since these information are not provided by the map file.</p>
        </blockquote>
        <h3>Memory viewer</h3>
        <p>The memory viewer tool is convenient to see the content of memory at any address. The address and size to dump can be provided via the text inputs. The address must be provided in <strong>hexadecimal</strong> whereas the size is provided in <strong>decimal</strong>.</p>
        <figure>
          <img src="imgs/help/memory.png" alt="Memory viewer" />
          <figcaption>Memory viewer</figcaption>
        </figure>

        <p>The provided address is a <strong>virtual address</strong> and not physical address. This is important since Zeal 8-bit Computer has an MMU, so each 16KB virtual pages can be mapped to any 16KB physical page.</p>
        <p>The dump memory lines are presented as follows:</p>
        <p><code>virtual address (physical address)      32-byte dump      ASCII representation</code></p>
        <p>This view also provides two buttons to dump the current ROM and (I2C) EEPROM content respectively.</p>
        <blockquote>
        <p><strong>Note:</strong> This view is only updated when the <code>dump</code> button is pressed. If a byte in memory changes, the view won't show the new value until the view is refreshed (<code>dump</code> button pressed)</p>
        </blockquote>
        <h3>UART monitor</h3>
        <p>Zeal 8-bit Computer provides has a UART interface. Even though it is a software UART implemented with the Z80 PIO, it can also be used on the emulator thanks to the cycle accurate emulation.</p>
        <figure>
          <img src="imgs/help/uart.png" alt="UART monitor" />
          <figcaption>UART monitor</figcaption>
        </figure>

        <p>This tool can be used to see the data sent by the computer through UART, but also to send text, including files. The baudrate can be configured by using the option menu.</p>
        <p>Keep in mind that if it seems like the monitor doesn't have any reaction when typing in the monitor, it is because the CPU is not currently listening on the UART, sending anything ot the UART.</p>
        <h3>Debug actions</h3>
        <p>The right panel is dedicated to debug actions. It contains the follow actions:</p>
        <figure>
          <img src="imgs/help/actions.png" alt="Debug actions" />
          <figcaption>Debug actions</figcaption>
        </figure>

        <ul>
        <li>Start/resume CPU execution (F9 shortcut)</li>
        <li>Step into (F10): clicking this button when performing step by step debugging will follow the destination of jump instructions such as <code>rst</code>, <code>call</code>, <code>jp</code>, <code>jr</code>...</li>
        <li>Step over (F11): clicking this button when performing step by step debugging will execute the following jump instructions but will break after it.</li>
        <li>Stop: stop the CPU execution, showing the registers value</li>
        <li>Reset: performs a CPU reset</li>
        <li>Clean: completely cleans the ROM, RAM and EEPROM in order to load a new program to the board. This feature is used when switching between pre-built ROMs</li>
        </ul>
        <h3>Breakpoint management</h3>
        <p>Just like a regular debugger, it is possible to put breakpoints that will stop the CPU execution, showing the current value of the CPU registers and code disassembly.</p>
        <figure>
          <img src="imgs/help/break.png" alt="Breakpoints" />
          <figcaption>Breakpoints</figcaption>
        </figure>

        <p>The text entry accepts <strong>hexadecimal</strong> values, with or without <code>0x</code> prefix. Moreover, if a <code>.map</code> file is provided, it is possible to write the name of label to break on. This is convenient to debug a program's function/routine that often has a different address.</p>
        <p>Breakpoints can be disabled by clicking on the red dot and re-enabled by clicking them again.</p>
        <p>It is currently not possible to completely remove breakpoints.</p>
        <h3>CPU registers</h3>
        <p>The left panel present a direct way to see the CPU register value when the CPU stops because of a breakpoint or a manual stop.</p>
        <figure>
          <img src="imgs/help/registers.png" alt="CPU Registers" />
          <figcaption>CPU Registers</figcaption>
        </figure>

        <p>The 16-bit registers, <code>BC</code>, <code>DE</code>, <code>HL</code>, <code>PC</code>, <code>SP</code> have an underlines value to show that they are clickable. By clinking on a value, the memory viewer will be opened and will show the content of the address.</p>
    </section>

    <section id="toppanel">
        <section id="debug">
        <table>
            <tr><td>A</td><td id="rega"></td></tr>
            <tr><td>B</td><td id="regb"></td></tr>
            <tr><td>C</td><td id="regc"></td></tr>
            <tr><td>D</td><td id="regd"></td></tr>
            <tr><td>E</td><td id="rege"></td></tr>
            <tr><td>H</td><td id="regh"></td></tr>
            <tr><td>L</td><td id="regl"></td></tr>
            <tr><td>IX</td><td id="regix" class="regaddr"></td></tr>
            <tr><td>IY</td><td id="regiy" class="regaddr"></td></tr>
            <tr><td>BC</td><td id="regbc" class="regaddr"></td></tr>
            <tr><td>DE</td><td id="regde" class="regaddr"></td></tr>
            <tr><td>HL</td><td id="reghl" class="regaddr"></td></tr>
            <tr><td>PC</td><td id="regpc" class="regaddr"></td></tr>
            <tr><td>SP</td><td id="regsp" class="regaddr"></td></tr>
            <tr><td>Flags</td><td id="flags"></td></tr>
        </table>

        <section id="romload">
            <label for="romchoice">Choose a pre-built ROM:</label>
            <img src="imgs/loading.gif" id="loading_img" alt="loading..." />
            <select name="romchoice" id="romchoice">
                <option value="">Loading...</option>
            </select>

            <section id="romadvanced">
                <a href="#">Advanced...</a>
            </section>
        </section>

        <section id="romfile">
            <div style="display: none;">
            <input type="radio" id="os" name="typebin" value="OS" checked>
            <label for="os">OS</label><br>
            <input type="radio" id="program" name="typebin" value="Program">
            <label for="program">Program</label><br>
            <input type="text" id="address" name="address" value="0x2000" />
            </div>
            <label for="file-input">System image:</label>
            <div class="help" title="File to load into the emulated ROM. It take be a single system binary or an image containing the system and a romdisk">?</div>
            <input type="file" id="file-input" placeholder="OS file" />
            <label for="file-dump">System map file:</label>
            <div class="help" title="Map file (text) generated by z88dk-z80asm containing the symbols of the binary image/file">?</div>
            <input type="file" id="file-dump" placeholder="OS dump" />
            <label for="eeprom-bin">EEPROM image:</label>
            <div class="help" title="Binary file to load into the emulated 64KB I2C EEPROM">?</div>
            <input type="file" id="eeprom-bin" placeholder="EEPROM image" />
            <button id="read-button">Read file(s)</button>
            <div id="statuspan">
            <h4>Ready?</h4>
            <div id="binready" class="status">System image</div>
            <div id="symready" class="status">Symbols</div>
            <div id="eepromready" class="status">EEPROM image</div>
            </div>
            <pre id="file-contents"></pre>
        </section>
        </section>

        <div id="container">
        <canvas id="screen" tabindex="1" style="outline: none;"></canvas>
        </div>

        <section id="rightpanel">
        <section class="menu" id="controls">
            <img id="continue" title="Continue (F9)" src="imgs/continue.png" alt="Continue" />
            <img id="step" title="Step (F10)" src="imgs/step.png" alt="Step" />
            <img id="stepover" title="Step Over (F11)" src="imgs/stepover.png" alt="Step over" />
            <img id="stop" title="Stop" src="imgs/stop.png" alt="Stop" />
            <img id="reset" title="Reset" src="imgs/restart.png" alt="Reset">
            <img id="clean" title="Clean" src="imgs/clean.png" alt="Clean">
        </section>

        <section class="menu">
            <section class="menutitle">
                <img class="menuicon" src="imgs/down-arrow.png" />Breakpoints</section>
            <section class="menucontent">
                <section id="newbp">
                    <input type="text" id="bpaddr" />
                    <button id="addbp">Add</button>
                </section>

                <section id="breakpoints">
                    <ul id="bps">
                    </ul>
                </section>
            </section>
        </section>

        <section class="menu">
            <section class="menutitle">
                <img class="menuicon" src="imgs/right-arrow.png" />Settings</section>
            <section class="menucontent" style="display: none;">
                <label for="theme">Switch theme:</label>
                <select id="theme" name="theme">
                    <option value="dark" selected>Dark (Default)</option>
                    <option value="light">Light</option>
                </select>
            </section>
        </section>

        </section>
    </section>


    <section class="bottompanel">
      <section class="tabs">
        <div class="tab">Disassemble</div>
        <div id="memory-tab" class="tab">Memory view</div>
        <div class="tab active">Terminal (UART)</div>
      </section>
      <section id="memdump" class="panel hidden">
      </section>
      <section id="memview" class="panel hidden">
        <section id="dumpfields">
          <input type="text" id="dumpaddr" placeholder="Hex address" />
          <input type="text" id="dumpsize" placeholder="Size" />
          <input type="button" id="dumpnow" value="Dump" />
          <input type="button" id="dump-button" value="Dump ROM" />
          <input type="button" id="dump-eeprom-button" value="Dump EEPROM" />
          <a id="dump-link" href="#" download="rom_dump.bin" style="display: none;">Dump ROM</a>
          <a id="dump-eeprom-link" href="#" download="eeprom_dump.bin" style="display: none;">Dump EEPROM</a>

        </section>
        <section class="memline">
            <section id="current_memaddr" class="memaddr"></section>
        </section>

        <section id="dumpcontent">
        </section>

      </section>
      <section id="uartview" class="panel">
        <input type="button" id="clearterm" value="Clear" />
        <label for="baudrate">Baudrate: </label>
        <select id="baudrate">
          <option value="57600">57600</option>
          <option value="38400">38400 </option>
          <option value="19200">19200</option>
          <option value="9600">9600</option>
        </select>
        <label for="uart-file">Send a file:</label>
        <input type="file" id="uart-file" placeholder="Send a file through UART" />
        <input type="button" id="uart-file-send" value="Send" />
        <div id="terminal"></div>
      </section>
    </section>

    <footer>
        <ul>
            <li><a href="#" id="about" data-target="about-message">About</a></li>
            <li><a href="#" id="help" data-target="help-message">Help</a></li>
            <li>©2022-2023 Zeal8bit</li>
        </ul>
    </footer>

    <script>
      const KB = 1024;
      /* 10MHz frequency */
      const CPUFREQ = 10000000;
      const TSTATES_US = 1/CPUFREQ * 1000000;

      function us_to_tstates(us) {
        return Math.floor(us / TSTATES_US);
      }

      var terminal = new Terminal();
      terminal.open(document.getElementById('terminal'));
    </script>
    <script src="jquery-3.6.0.min.js"></script>
    <!-- Disassembler-related -->
    <script>
        jQuery.fn.visible = function() {
            return this.css('visibility', 'visible');
        };

        jQuery.fn.invisible = function() {
            return this.css('visibility', 'hidden');
        };

        function disassembler_hex(n) {
            return "$" + n.toString(16);
        }

        function hex(str, noprefix, digits) {
            if (typeof digits === "undefined") {
                digits = 4;
            }
            var result = "";
            for (var i = 0; i < digits; i++)
                result += "0";

            const leading = (result + str.toString(16).toUpperCase()).substr(-digits);

            if (noprefix) {
                return leading;
            }
            return "0x" + leading;
        }

        function hex8(str, noprefix) {
            const value = hex(str, true);
            return (noprefix ? "" : "0x") + value.substring(2);
        }

        function hex16(high, lower, noprefix) {
            const value = (high << 8) + lower;
            return (noprefix ? "" : "0x") + hex(value, true);
        }
    </script>
    <script src="disassembler/opcodes_cb.js"></script>
    <script src="disassembler/opcodes_ed.js"></script>
    <script src="disassembler/opcodes_ixiy.js"></script>
    <script src="disassembler/disassembler.js"></script>
    <!-- Emulation-related -->
    <script src="characters.js"></script>
    <script src="screen.js"></script>
    <script src="rom.js"></script>
    <script src="pio.js"></script>
    <script src="uart.js"></script>
    <script src="keyboard.js"></script>
    <script src="i2c.js"></script>
    <script src="ram.js"></script>
    <script src="mmu.js"></script>
    <script src="Z80.js"></script>
    <script src="machine.js"></script>
    <script src="zeal.js" type="text/javascript"></script>
    <script src="menus.js"></script>
  </body>
</html>
